package injector;

import annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.lang.reflect.Field;

public class Injector {
	
	/**
	 *  Liste des implementations d'interfaces
	 */
	private List<Binder<?>> list;
	
	/**
	 * Constructeur
	 */
	public Injector() {
        list = new ArrayList<Binder<?>>();           
	}
	
	/**
	 * Methode permettant de lier une interface a une de ses implementations
	 * @param iface Interface a lier
	 * @return Un Binder
	 */
	public <T> Binder<?> bind(Class<T> iface)
	{
		Binder<?> binder = new Binder<T>(iface);
		list.add(binder);
		return binder;
	}
	
	/**
	 * Creation d'une nouvelle instance d'une classe implementant une interface
	 * @param iface Interface a implementer
	 * @return Nouvelle instance creee
	 */
	public <T> T newInstance(Class<T> iface)
	{
		for (Binder<?> binder:list) {
			if (binder.apply(iface)) {
				return (T) binder.newInstance();
			}
		}
		throw new IllegalArgumentException();	
	}

	/**
	 * Injection d'une instance
	 * @param obj Objet a injecter
	 * @return Objet injecte
	 */
	public Object inject(Object obj)
	{
		// Recuperation des attributs de l'objet
		for (Field field : obj.getClass().getDeclaredFields()) {
			// Traitement des attributs annotes avec @Inject 
			if (field.isAnnotationPresent(Inject.class)) {
				// Si un binding existe pour cette interface
				for (Binder<?> b : list) {
					if (b.getIface().getName() == field.getType().getName()) { 
						inject(field);
					}
				}
			}
		}       

		return obj;	
	}
}
